﻿using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PasteCluster;
using TestCluster.redismodel;

namespace TestCluster
{
    /// <summary>
    /// HostedService任务
    /// </summary>
    public class StartHostedService : IHostedService
    {

        private PasteClusterHandler _cluster_handler;
        private IAppCache _appCache;
        private ILogger<StartHostedService> _logger;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pasteClusterHandler"></param>
        /// <param name="appCache"></param>
        /// <param name="logger"></param>
        public StartHostedService(PasteClusterHandler pasteClusterHandler, IAppCache appCache, ILogger<StartHostedService> logger)
        {
            //_serviceProvider = serviceProvider;
            _cluster_handler = pasteClusterHandler;
            _appCache = appCache;
            _logger = logger;
        }

        /// <summary>
        /// hashset模式 field为host value为pastenodemodel
        /// </summary>
        private const string node_list_cache_key = "hash:node:autolist";
        private System.Timers.Timer _timer;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            //如果已知当前节点的Host(这里示例默认为80端口)信息，可以用下方的函数写入,也可以在启动的时候写入配置中
            // -e ClusterConfig:CurrentHost="http://192.168.1.100"
            //如果使用PasteSpider部署，则是-e ClusterConfig:CurrentHost="http://{{App.ProAddress}}"
            //_cluster_handler.Register("http://192.168.1.100",0,0);
            //启动集群中的当前节点(在这之前必须要确认当前节点的host是多少)
            _cluster_handler.StartCluster();

            var _current_node = _cluster_handler.CurrentNode;
            if (_current_node != null)
            {
                var _currentInfo = Newtonsoft.Json.JsonConvert.SerializeObject(_current_node);
                await _appCache.HashSetAsync(node_list_cache_key, _current_node.host, _currentInfo);
            }

            var reads = await _appCache.HashGetAllAsync(node_list_cache_key);
            if (reads != null && reads.Length > 0)
            {
                foreach (var _item in reads)
                {
                    var _nodeBody = _item.Value.ToString();
                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} write node to list !");
                    if (!String.IsNullOrEmpty(_nodeBody))
                    {
                        var _node = Newtonsoft.Json.JsonConvert.DeserializeObject<PasteNodeModel>(_nodeBody);
                        if (_node != null && _node != default)
                        {
                            _cluster_handler.AddNodeToList(_node);
                        }
                    }
                }
                _cluster_handler.ScanMaster();//执行扫描，找master加入，因为你不知道在你这个节点前可能已经有集群形成了
            }

            //读取集群产生的数据，比如其他节点发送的数据等,这里一般是业务相关的消息
            ReadClusterChannel();

            #region 使用定时器产生模拟集群数据产生
            _timer = new System.Timers.Timer();
            hit_index = new Random().Next(1, 100);
            _timer.Interval = 1000;
            _timer.AutoReset = true;
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
            #endregion
            //return Task.CompletedTask;
        }

        private int hit_index = 5;

        /// <summary>
        /// 测试产生数据进行交互
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                hit_index--;
                if (hit_index == 0)
                {
                    var _second = DateTime.Now.Second;
                    if (_second % 2 == 0)
                    {
                        //模拟发送给主节点
                        _cluster_handler.PushMsgToMaster($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} FROM NODE {_cluster_handler.CurrentHost} !");
                    }
                    else
                    {
                        //模拟发送给所有节点
                        _cluster_handler.PushMsgToAll($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} FROM {_cluster_handler.CurrentHost} !");
                    }
                    hit_index = new Random().Next(300, 600);
                }
            }
            catch (Exception exl)
            {
                _logger.LogException(exl);
            }
        }

        /// <summary>
        /// 处理集群产生的数据
        /// </summary>
        private async void ReadClusterChannel()
        {
            try
            {
                var _info = await _cluster_handler.ChannelCluster.Reader.ReadAsync();
                if (_info != null && _info != default)
                {
                    switch (_info.msg_type)
                    {
                        case 1:
                            {
                                //当前节点成为master _info.body ==PasteMasterResponse.JsonString
                            }
                            break;
                        case 2:
                            {
                                //当前节点不再是master _info.body ==PasteMasterResponse.JsonString
                            }
                            break;
                        case 3:
                            {
                                //有节点加入 _info.body == PasteNodeModel.JsonString
                            }
                            break;
                        case 4:
                            {
                                if (_cluster_handler.CurrentIsMaster)
                                {
                                    var _node = Newtonsoft.Json.JsonConvert.DeserializeObject<PasteNodeModel>(_info.body);
                                    if (_node != null && _node != default)
                                    {
                                        if (!String.IsNullOrEmpty(_node.host))
                                        {
                                            await _appCache.HashDeleteAsync(node_list_cache_key, _node.host);
                                        }
                                    }
                                }
                            }
                            break;
                        default:
                            {
                                //业务代码 // _info.body是什么消息格式要基于业务而定
                            }
                            break;
                    }
                }
            }
            catch (Exception exl)
            {
                _logger.LogException(exl);
                await Task.Delay(1000);
            }
            finally
            {
                ReadClusterChannel();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            _cluster_handler.Dispose();
            return Task.CompletedTask;
        }
    }
}
